package com.wandian.texas;

import java.net.*;
import java.nio.channels.*;
import java.nio.*;
import java.io.*;
import java.nio.charset.*;
import java.util.*;

import com.wandian.util.Log;
import com.wandian.util.StringUtil;
	/**   
	* @author long
	* @QQ 108232706
	* @version 1.0   
	*/   
	public class EchoClient
{
	private SocketChannel socketChannel = null;
	private ByteBuffer sendBuffer = ByteBuffer.allocate(1024);
	private ByteBuffer receiveBuffer = ByteBuffer.allocate(1024);
	private Charset charset = Charset.forName("UTF-8");
	private Selector selector;

	public EchoClient() throws IOException
	{
		socketChannel = SocketChannel.open();
		InetAddress ia = InetAddress.getLocalHost();
		InetSocketAddress isa = new InetSocketAddress(ia, 9999);
		socketChannel.connect(isa); // 采用阻塞模式连接服务器
		socketChannel.configureBlocking(false); // 设置为非阻塞模式
		System.out.println("与服务器的连接建立成功");
		selector = Selector.open();
	}

	public static void main(String args[]) throws IOException
	{
		final EchoClient client = new EchoClient();
		Thread receiver = new Thread()
		{ // 创建Receiver线程
			public void run()
			{
				client.receiveFromUser(); // 接收用户向控制台输入的数据
			}
		};
		receiver.start(); // 启动Receiver线程
		client.talk();
	}

	private void printByteBuffer(String msg, int position, int length, ByteBuffer contentBuffer) {
		// 转成16进制字符串
		int oldposition = contentBuffer.position();
		contentBuffer.position(0);
		String hs = "";
		String tmp = "";
		for (int n = 0; n < length; n++) {
			// 整数转成十六进制表示
			tmp = (java.lang.Integer.toHexString(contentBuffer.get() & 0XFF));
			if (tmp.length() == 1) {
				hs = hs + "0" + tmp + ",";
			} else {
				hs = hs + tmp + ",";
			}
		}
		contentBuffer.position(oldposition);// 恢复起初位置
		tmp = null;
		hs.toUpperCase();// 转成大写
		String result = msg + " length:" + length + " content:" + hs;
		Log.info(result);
	}

	public void receiveFromUser()
	{ // 接收用户从控制台输入的数据，把它放到sendBuffer中
		try
		{
			System.out.println("cmd 8 UserLoginCmd.  9 TableListCmd, 10 UserInfoCmd ");
			BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
			String msg = null;
			while ((msg = localReader.readLine()) != null)
			{
				synchronized (sendBuffer)
				{
					// this.len = iobuf.getInt();
					// this.code = iobuf.getShort();
					// this.playerId = iobuf.getInt();
					// this.empty1 = iobuf.getInt();
					// this.empty2 = iobuf.getInt();4*4+2*2
					// msg = new String(msg.getBytes("iso-8859-1"), "gb2312");
					ByteBuffer contentBuffer = ByteBuffer.allocate(1024);
					contentBuffer.order(ByteOrder.LITTLE_ENDIAN);
					ByteBuffer tempBuffer = encode(msg, true);
					printByteBuffer("发送消息：", 0, tempBuffer.remaining(), tempBuffer);
					contentBuffer.putInt(29099);// head
					contentBuffer.putInt(tempBuffer.remaining() + 22);// length
					short cmd=Short.parseShort(msg.split(",")[0]);
					contentBuffer.putShort((short) cmd);// cmd
					contentBuffer.putInt(1);// temp1
					contentBuffer.putInt(2);// temp2
					contentBuffer.putInt(3);// temp3
					contentBuffer.put(tempBuffer);
					contentBuffer.flip();
					sendBuffer.put(contentBuffer);
					// 转成16进制字符串
					String hs = "";
					String tmp = "";
					contentBuffer.position(0);
					for (int n = 0; n < contentBuffer.limit(); n++) {
						// 整数转成十六进制表示
						tmp = (java.lang.Integer.toHexString(contentBuffer.get() & 0XFF));
						if (tmp.length() == 1) {
							hs = hs + "0" + tmp + ",";
						} else {
							hs = hs + tmp + ",";
						}
					}
					tmp = null;
					hs.toUpperCase();// 转成大写
					String result = "发送数据  length:" + contentBuffer.limit() + " content:" + hs;
					Log.info(result);
				}
				if (msg.equals("bye"))
					break;
			}
		} catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	public void printBytes(String msg, byte[] bytes, int length) {
		String result = msg + " length:" + length + " content:" + StringUtil.byte2hex(bytes, length);
		Log.info(result);
	}

	public void talk()
	{ // 接收和发送数据
		try {
			socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
		} catch (ClosedChannelException e1) {
			// TODO 自动生成的 catch 块
			e1.printStackTrace();
		}
		try {
			while (selector.select() > 0)
			{
				Set readyKeys = selector.selectedKeys();
				Iterator it = readyKeys.iterator();
				while (it.hasNext())
				{
					SelectionKey key = null;
					try
					{
						key = (SelectionKey) it.next();
						it.remove();
						if (key.isReadable())
						{
							receive(key);
						}
						if (key.isWritable())
						{
							send(key);
						}
					} catch (IOException e)
					{
						e.printStackTrace();
						try
						{
							if (key != null)
							{
								key.cancel();
								key.channel().close();
							}
						} catch (Exception ex)
						{
							e.printStackTrace();
						}
					}
				}// #while
			}
		} catch (IOException e) {
			e.printStackTrace();
			try {
				selector.close();
				socketChannel.close();
			} catch (IOException e1) {
				// TODO 自动生成的 catch 块
				e1.printStackTrace();
			}

		}// #while
	}

	public void send(SelectionKey key) throws IOException
	{
		// 发送sendBuffer中的数据
		SocketChannel socketChannel = (SocketChannel) key.channel();
		synchronized (sendBuffer)
		{
			sendBuffer.flip(); // 把极限设为位置，把位置设为零
			socketChannel.write(sendBuffer); // 发送数据，写的时候覆盖了之前的数据，
			sendBuffer.compact(); // 删除已经发送的数据
		}
	}

	public void receive(SelectionKey key) throws IOException
	{
		// 接收EchoServer发送的数据，把它放到receiveBuffer中
		// 如果receiveBuffer中有一行数据，就打印这行数据，然后把它从receiveBuffer中删除
		SocketChannel socketChannel = (SocketChannel) key.channel();
		socketChannel.read(receiveBuffer);
		receiveBuffer.flip();
		printByteBuffer("收到服务器数据", 0, receiveBuffer.remaining(), receiveBuffer);
		receiveBuffer.position(22);
		String receiveData = decode(receiveBuffer, true);
		Log.info("服务器say：" + receiveData);
		if (receiveData.equals("bye"))
		{
			key.cancel();
			socketChannel.close();
			System.out.println("关闭与服务器的连接");
			selector.close();
			System.exit(0); // 结束程序
		}
		// ByteBuffer temp = encode(receiveData);
		// receiveBuffer.position(temp.limit());
		receiveBuffer.compact(); // 删除已经打印的数据
	}

	public String decode(ByteBuffer buffer, boolean ischarset)
	{ // 解码
		if (ischarset) {
			CharBuffer charBuffer = charset.decode(buffer);
			return charBuffer.toString();
		} else {
			byte[] bytes = new byte[buffer.remaining()];
			buffer.get(bytes, 0, buffer.remaining());
			try {
				return new String(bytes, "UTF-8");
			} catch (UnsupportedEncodingException e) {
				return "";
			}
		}

	}

	public ByteBuffer encode(String str, boolean ischarset)
	{ // 编码
		// Log.info("发送到缓冲区:" + str);
		if (ischarset) {
			return charset.encode(str);
		} else {
			byte[] bytes;
			ByteBuffer temBuffer = null;
			try {
				bytes = str.getBytes("utf-8");
				temBuffer = ByteBuffer.allocate(bytes.length);
				temBuffer.put(bytes);
				temBuffer.flip();
			} catch (UnsupportedEncodingException e) {
			}

			return temBuffer;
		}

	}
}